<template>
    <div ref="wbgl" class="my_wbgl"></div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import * as THREE from 'three';
/** Orbit controls（轨道控制器）可以使得相机围绕目标进行轨道运动。 */
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
/** 性能监控 */
import Stats from 'three/examples/jsm/libs/stats.module.js';

const wbgl = ref();

const init = () => {
    /** 一、创建一个三维场景 */
    const scene = new THREE.Scene();
    // 给三维场景添加背景
    scene.background = new THREE.Color ('#000e1c');
    /** 二、创建一个投影相机 */
    /**
     * PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )
     * fov — 摄像机视锥体垂直视野角度
     * aspect — 摄像机视锥体长宽比
     * near — 摄像机视锥体近端面
     * far — 摄像机视锥体远端面
     */
    // 定义相机输出的画布尺寸
    const rect = wbgl.value.getBoundingClientRect();
    const width = rect.width;
    console.log("🚀 ~ init ~ rect.width;:", rect.width)
    const height = rect.height;

    // 创建一个透视相机
    const camera = new THREE.PerspectiveCamera(75, width / height, 1, 10000); // 透视相机（PerspectiveCamera）
    // 设置相机的位置
    camera.position.set(800, 500, 800);
    // 设置相机的观察点
    // camera.lookAt(0, 0, 0);  // 坐标定义观察点
    camera.lookAt(300, 0, 300); // 指向具体的模型
    // 将相机添加到三维场景中
    scene.add(camera);

    /** 三、WebGLRenderer渲染器-渲染出物体 */
    // 创建一个渲染器
    const renderer = new THREE.WebGLRenderer({
        antialias: true, // 开启抗锯齿
    });
    // 设置渲染器的尺寸
    renderer.setSize(width, height);

    // 辅助坐标系
    const axesHelper = new THREE.AxesHelper(10000);
    scene.add(axesHelper);

    /** 四、轨道控制器 */
    // 设置轨道控制器
    const controls = new OrbitControls(camera, renderer.domElement);
    // 设置控制器阻尼
    controls.enableDamping = false;
    controls.addEventListener('change', () => {
        // renderer.render(scene, camera); // 有动画渲染这里就可以不用渲染
    });

    /** 五、光源 */
    // 新建一个几何体，并且加上漫反射网格材质
    const geometry2 = new THREE.BoxGeometry(20, 20, 20);
    const material2 = new THREE.MeshLambertMaterial({ color: 0x00a7ba });
    const mesh = new THREE.Mesh(geometry2, material2);
    mesh.position.set(300, 240, 300);
    scene.add(mesh);

    // 平行光(有方向)
    const directionalLight = new THREE.DirectionalLight(0xffffff,1.5);
    directionalLight.position.set(1000, 800, 1000);
    // directionalLight.target(0, 0, 0) // 设置照射方向(默认 0 0 0)
    scene.add(directionalLight);

    // 可视化平行光
    const directionalLightHelper = new THREE.DirectionalLightHelper(directionalLight, 10, 0x00ffff);
    scene.add(directionalLightHelper);

    // 点光源（四周发散）
    // const pointLight = new THREE.PointLight(0xffffff, 1);
    // pointLight.decay = 1; // 衰减
    // pointLight.position.set(320, 100, 100);
    // scene.add(pointLight)

    // 环境光（没有方向）
    // const ambientLight = new THREE.AmbientLight(0xffffff, 3);
    // ambientLight.position.set(300, 100, 100);
    // scene.add(ambientLight);


    // 可视化光源
    // const pointLightHelper = new THREE.PointLightHelper(ambientLight, 10);
    // scene.add(pointLightHelper);


    // 渲染三维场景
    renderer.render(scene, camera);
    // 将渲染器的输出canvas添加到页面中
    wbgl.value.appendChild(renderer.domElement);
    const stats = new Stats();
    stats.domElement.style.position = 'absolute'
    stats.domElement.style.left = 'calc(100% - 80px)'
    stats.domElement.style.top = '0px'
    wbgl.value.appendChild(stats.dom);

    /** 生成大量模型测试性能 */
    // const num = 1000;
    // for (let i = 0; i < num; i++) {
    //     // 新建一个几何体，并且加上漫反射网格材质
    //     let long = Math.random() * 20
    //     const geometry3 = new THREE.BoxGeometry(long, long, long);
    //     const material3 = new THREE.MeshLambertMaterial({ color: 0x00a7ba });
    //     const mesh3 = new THREE.Mesh(geometry3, material3);
    //     mesh3.position.set(Math.random() * 1000 - 500, Math.random() * 1000 - 500, Math.random() * 1000 - 500);
    //     scene.add(mesh3);
    // }

    /** 沿着X轴生成一列模型 */
    // for(let i = 0; i < 100; i++) {
    //     // 新建一个几何体，并且加上漫反射网格材质
    //     const geometry3 = new THREE.BoxGeometry(10, 10, 10);
    //     const material3 = new THREE.MeshLambertMaterial({ color: 0x00a7ba })
    //     const mesh3 = new THREE.Mesh(geometry3, material3);
    //     mesh3.position.set(i * 30, 0, 0);
    //     scene.add(mesh3);
    // }

    /** 沿着X0Z平面阵列 */
    for(let i = 0; i < 20; i++) {
        for(let j = 0; j < 20; j++) {
            // 新建一个几何体，并且加上漫反射网格材质
            const geometry3 = new THREE.BoxGeometry(10, 10, 10)
            const material3 = new THREE.MeshLambertMaterial({ color: 0x00a7ba })
            const mesh3 = new THREE.Mesh(geometry3, material3);
            mesh3.position.set(i * 30, 0, j * 30);
            scene.add(mesh3);
        }
    }

    /** 地板 */
    const floorGeometry = new THREE.PlaneGeometry(6000, 6000, 10, 10);
    const floorMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
    const floor = new THREE.Mesh(floorGeometry, floorMaterial);
    floor.position.set(0, -5, 0);
    floor.rotation.x = -Math.PI / 2;
    scene.add(floor);


    /** 动画 */
    // const clock = new THREE.Clock(); // 创建一个时钟对象
    const animate = () => {
        stats.update();
        // const spt = clock.getDelta() * 1000;
        // console.log("🚀 ~ animate ~ spt:", spt)
        // console.log("🚀 ~ animate ~ 渲染帧率:", 1000/spt)
        mesh.rotateY(0.01); // 周期性旋转，每次旋转0.01弧度
        renderer.render(scene, camera); // 周期性执行渲染
        window.requestAnimationFrame(animate);
    }
    animate();

    /** 窗口变化重新设置画布大小和相机缩放 */
    window.onresize = () => {
        const wbglInfo = wbgl.value.getBoundingClientRect();

        renderer.setSize(wbglInfo.width, wbglInfo.height);
        camera.aspect = wbglInfo.width / wbglInfo.height;
        camera.updateProjectionMatrix();
    }
}

onMounted(() => {
    init();
})

</script>
<style scoped>
.my_wbgl {
    position: relative;
}
</style>